home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / imagemap / imap_circle.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-20  |  11.3 KB  |  406 lines

  1. /*
  2.  * This is a plug-in for the GIMP.
  3.  *
  4.  * Generates clickable image maps.
  5.  *
  6.  * Copyright (C) 1998-1999 Maurits Rijk  lpeek.mrijk@consunet.nl
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  *
  22.  */
  23.  
  24. #include "config.h"
  25.  
  26. #include <stdlib.h>
  27. #include <math.h>
  28.  
  29. #include "imap_circle.h"
  30. #include "libgimp/stdplugins-intl.h"
  31. #include "imap_main.h"
  32. #include "imap_misc.h"
  33. #include "imap_object_popup.h"
  34. #include "imap_table.h"
  35.  
  36. #include "circle.xpm"
  37.  
  38. static gboolean circle_is_valid(Object_t *obj);
  39. static Object_t *circle_clone(Object_t *obj);
  40. static void circle_assign(Object_t *obj, Object_t *des);
  41. static void circle_draw(Object_t* obj, GdkWindow *window, GdkGC* gc);
  42. static void circle_draw_sashes(Object_t* obj, GdkWindow *window, GdkGC* gc);
  43. static MoveSashFunc_t circle_near_sash(Object_t *obj, gint x, gint y);
  44. static gboolean circle_point_is_on(Object_t *obj, gint x, gint y);
  45. static void circle_get_dimensions(Object_t *obj, gint *x, gint *y,
  46.                   gint *width, gint *height);
  47. static void circle_resize(Object_t *obj, gint percentage_x, gint percentage_y);
  48. static void circle_move(Object_t *obj, gint dx, gint dy);
  49. static gpointer circle_create_info_widget(GtkWidget *frame);
  50. static void circle_fill_info_tab(Object_t *obj, gpointer data);
  51. static void circle_set_initial_focus(Object_t *obj, gpointer data);
  52. static void circle_update(Object_t* obj, gpointer data);
  53. static void circle_write_csim(Object_t* obj, gpointer param, 
  54.                   OutputFunc_t output);
  55. static void circle_write_cern(Object_t* obj, gpointer param, 
  56.                   OutputFunc_t output);
  57. static void circle_write_ncsa(Object_t* obj, gpointer param, 
  58.                   OutputFunc_t output);
  59. static char** circle_get_icon_data(void);
  60.  
  61. static ObjectClass_t circle_class = {
  62.    N_("Circle"),
  63.    NULL,            /* info_dialog */
  64.    NULL,            /* icon */
  65.    NULL,            /* mask */
  66.  
  67.    circle_is_valid,
  68.    NULL,            /* circle_destruct */
  69.    circle_clone,
  70.    circle_assign,
  71.    NULL,            /* circle_normalize */
  72.    circle_draw,
  73.    circle_draw_sashes,
  74.    circle_near_sash,
  75.    circle_point_is_on,
  76.    circle_get_dimensions,
  77.    circle_resize,
  78.    circle_move,
  79.    circle_create_info_widget,
  80.    circle_fill_info_tab,    /* circle_update_info_widget */
  81.    circle_fill_info_tab,
  82.    circle_set_initial_focus,
  83.    circle_update,
  84.    circle_write_csim,
  85.    circle_write_cern,
  86.    circle_write_ncsa,
  87.    object_do_popup,
  88.    circle_get_icon_data
  89. };
  90.  
  91. Object_t*
  92. create_circle(gint x, gint y, gint r)
  93. {
  94.    Circle_t *circle = g_new(Circle_t, 1);
  95.    circle->x = x;
  96.    circle->y = y;
  97.    circle->r = r;
  98.    return object_init(&circle->obj, &circle_class);
  99. }
  100.  
  101. static gboolean
  102. circle_is_valid(Object_t *obj)
  103. {
  104.    return ObjectToCircle(obj)->r > 0;
  105. }
  106.  
  107. static Object_t*
  108. circle_clone(Object_t *obj)
  109. {
  110.    Circle_t *circle = ObjectToCircle(obj);
  111.    Circle_t *clone = g_new(Circle_t, 1);
  112.  
  113.    clone->x = circle->x;
  114.    clone->y = circle->y;
  115.    clone->r = circle->r;
  116.    return &clone->obj;
  117. }
  118.  
  119. static void
  120. circle_assign(Object_t *obj, Object_t *des)
  121. {
  122.    Circle_t *src_circle = ObjectToCircle(obj);
  123.    Circle_t *des_circle = ObjectToCircle(des);
  124.    des_circle->x = src_circle->x;
  125.    des_circle->y = src_circle->y;
  126.    des_circle->r = src_circle->r;
  127. }
  128.  
  129. static void
  130. circle_draw(Object_t *obj, GdkWindow *window, GdkGC *gc)
  131. {
  132.    Circle_t *circle = ObjectToCircle(obj);
  133.    draw_circle(window, gc, FALSE, circle->x, circle->y, circle->r);
  134. }
  135.  
  136. static void
  137. circle_draw_sashes(Object_t *obj, GdkWindow *window, GdkGC *gc)
  138. {
  139.    Circle_t *circle = ObjectToCircle(obj);
  140.    draw_sash(window, gc, circle->x - circle->r, circle->y - circle->r);
  141.    draw_sash(window, gc, circle->x + circle->r, circle->y - circle->r);
  142.    draw_sash(window, gc, circle->x - circle->r, circle->y + circle->r);
  143.    draw_sash(window, gc, circle->x + circle->r, circle->y + circle->r);
  144. }
  145.  
  146. static gint sash_x;
  147. static gint sash_y;
  148.  
  149. static void
  150. move_sash(Object_t *obj, gint dx, gint dy)
  151. {
  152.    Circle_t *circle = ObjectToCircle(obj);
  153.    gint rx, ry;
  154.    sash_x += dx;
  155.    sash_y += dy;
  156.  
  157.    rx = abs(circle->x - sash_x);
  158.    ry = abs(circle->y - sash_y);
  159.    circle->r = (rx > ry) ? rx : ry;
  160. }
  161.  
  162. static void 
  163. circle_resize(Object_t *obj, gint percentage_x, gint percentage_y)
  164. {
  165.    Circle_t *circle = ObjectToCircle(obj);
  166.    circle->x = circle->x * percentage_x / 100;
  167.    circle->y = circle->y * percentage_y / 100;
  168.    circle->r = circle->r * ((percentage_x < percentage_y) 
  169.                 ? percentage_x : percentage_y) / 100;
  170. }
  171.  
  172. static MoveSashFunc_t
  173. circle_near_sash(Object_t *obj, gint x, gint y)
  174. {
  175.    Circle_t *circle = ObjectToCircle(obj);
  176.    sash_x = x;
  177.    sash_y = y;
  178.    if (near_sash(circle->x - circle->r, circle->y - circle->r, x, y) ||
  179.        near_sash(circle->x + circle->r, circle->y - circle->r, x, y) ||
  180.        near_sash(circle->x - circle->r, circle->y + circle->r, x, y) ||
  181.        near_sash(circle->x + circle->r, circle->y + circle->r, x, y))
  182.       return move_sash;
  183.    return NULL;
  184. }
  185.  
  186. static gboolean
  187. circle_point_is_on(Object_t *obj, gint x, gint y)
  188. {
  189.    Circle_t *circle = ObjectToCircle(obj);
  190.    x -= circle->x;
  191.    y -= circle->y;
  192.    return x * x + y * y <= circle->r * circle->r;
  193. }
  194.  
  195. static void 
  196. circle_get_dimensions(Object_t *obj, gint *x, gint *y,
  197.               gint *width, gint *height)
  198. {
  199.    Circle_t *circle = ObjectToCircle(obj);
  200.    *x = circle->x - circle->r;
  201.    *y = circle->y - circle->r;
  202.    *width = *height = 2 * circle->r;
  203. }
  204.  
  205. static void
  206. circle_move(Object_t *obj, gint dx, gint dy)
  207. {
  208.    Circle_t *circle = ObjectToCircle(obj);
  209.    circle->x += dx;
  210.    circle->y += dy;
  211. }
  212.  
  213. typedef struct {
  214.    Object_t  *obj;
  215.    GtkWidget *x;
  216.    GtkWidget *y;
  217.    GtkWidget *r;
  218. } CircleProperties_t;
  219.  
  220. static void
  221. x_changed_cb(GtkWidget *widget, gpointer data)
  222. {
  223.    Object_t *obj = ((CircleProperties_t*) data)->obj;
  224.    gint x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  225.    ObjectToCircle(obj)->x = x;
  226.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  227. }
  228.  
  229. static void
  230. y_changed_cb(GtkWidget *widget, gpointer data)
  231. {
  232.    Object_t *obj = ((CircleProperties_t*) data)->obj;
  233.    gint y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  234.    ObjectToCircle(obj)->y = y;
  235.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  236. }
  237.  
  238. static void
  239. r_changed_cb(GtkWidget *widget, gpointer data)
  240. {
  241.    Object_t *obj = ((CircleProperties_t*) data)->obj;
  242.    gint r = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  243.    ObjectToCircle(obj)->r = r;
  244.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  245. }
  246.  
  247. static gpointer
  248. circle_create_info_widget(GtkWidget *frame)
  249. {
  250.    CircleProperties_t *props = g_new(CircleProperties_t, 1);
  251.    GtkWidget *table;
  252.    gint max_width = get_image_width();
  253.    gint max_height = get_image_height();
  254.  
  255.    table = gtk_table_new(3, 3, FALSE);
  256.    gtk_container_add(GTK_CONTAINER(frame), table);
  257.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  258.  
  259.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  260.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  261.    gtk_widget_show(table);
  262.    
  263.    create_label_in_table(table, 0, 0, _("Center x:"));
  264.    props->x = create_spin_button_in_table(table, 0, 1, 1, 0, max_width - 1);
  265.    gtk_signal_connect(GTK_OBJECT(props->x), "changed", 
  266.               (GtkSignalFunc) x_changed_cb, (gpointer) props);
  267.    create_label_in_table(table, 0, 2, _("pixels"));
  268.  
  269.    create_label_in_table(table, 1, 0, _("Center y:"));
  270.    props->y = create_spin_button_in_table(table, 1, 1, 1, 0, max_height - 1);
  271.    gtk_signal_connect(GTK_OBJECT(props->y), "changed", 
  272.               (GtkSignalFunc) y_changed_cb, (gpointer) props);
  273.    create_label_in_table(table, 1, 2, _("pixels"));
  274.  
  275.    create_label_in_table(table, 2, 0, _("Radius:"));
  276.    props->r = create_spin_button_in_table(table, 2, 1, 1, 1, G_MAXINT);
  277.    gtk_signal_connect(GTK_OBJECT(props->r), "changed", 
  278.               (GtkSignalFunc) r_changed_cb, (gpointer) props);
  279.    create_label_in_table(table, 2, 2, _("pixels"));
  280.  
  281.    return props;
  282. }
  283.  
  284. static void 
  285. circle_fill_info_tab(Object_t *obj, gpointer data)
  286. {
  287.    Circle_t *circle = ObjectToCircle(obj);
  288.    CircleProperties_t *props = (CircleProperties_t*) data;
  289.  
  290.    props->obj = obj;
  291.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->x), circle->x);
  292.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->y), circle->y);
  293.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->r), circle->r);
  294. }
  295.  
  296. static void 
  297. circle_set_initial_focus(Object_t *obj, gpointer data)
  298. {
  299.    CircleProperties_t *props = (CircleProperties_t*) data;
  300.    gtk_widget_grab_focus(props->x);
  301. }
  302.  
  303. static void 
  304. circle_update(Object_t* obj, gpointer data)
  305. {
  306.    Circle_t *circle = ObjectToCircle(obj);
  307.    CircleProperties_t *props = (CircleProperties_t*) data;
  308.  
  309.    circle->x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->x));
  310.    circle->y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->y));
  311.    circle->r = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->r));
  312. }
  313.  
  314. static void
  315. circle_write_csim(Object_t *obj, gpointer param, OutputFunc_t output)
  316. {
  317.    Circle_t *circle = ObjectToCircle(obj);
  318.    output(param, "\"circle\" coords=\"%d,%d,%d\"", circle->x, circle->y,
  319.       circle->r);
  320. }
  321.  
  322. static void
  323. circle_write_cern(Object_t *obj, gpointer param, OutputFunc_t output)
  324. {
  325.    Circle_t *circle = ObjectToCircle(obj);
  326.    output(param, "circ (%d,%d) %d", circle->x, circle->y, circle->r);
  327. }
  328.  
  329. static void
  330. circle_write_ncsa(Object_t *obj, gpointer param, OutputFunc_t output)
  331. {
  332.    Circle_t *circle = ObjectToCircle(obj);
  333.    output(param, "circle %s %d,%d %d,%d", obj->url,
  334.       circle->x, circle->y, circle->x, circle->y + circle->r);
  335. }
  336.  
  337. static char** 
  338. circle_get_icon_data(void)
  339. {
  340.    return circle_xpm;
  341. }
  342.  
  343. static gint _start_x, _start_y;
  344.  
  345. static Object_t*
  346. circle_factory_create_object1(gint x, gint y)
  347. {
  348.    _start_x = x;
  349.    _start_y = y;
  350.    return create_circle(x, y, 0);
  351. }
  352.  
  353. static void
  354. circle_factory_set_xy1(Object_t *obj, guint state, gint x, gint y)
  355. {
  356.    Circle_t *circle = ObjectToCircle(obj);
  357.  
  358.    circle->x = (_start_x + x) / 2;
  359.    circle->y = (_start_y + y) / 2;
  360.    x -= _start_x;
  361.    y -= _start_y;
  362.    circle->r = (gint) sqrt(x * x + y * y) / 2;
  363.  
  364.    main_set_dimension(circle->r, circle->r);
  365. }
  366.  
  367. static ObjectFactory_t circle_factory1 = {
  368.    NULL,            /* Object pointer */
  369.    NULL,            /* Finish func */
  370.    NULL,            /* Cancel func */
  371.    circle_factory_create_object1,
  372.    circle_factory_set_xy1
  373. };
  374.  
  375. static Object_t*
  376. circle_factory_create_object2(gint x, gint y)
  377. {
  378.    return create_circle(x, y, 0);
  379. }
  380.  
  381. static void
  382. circle_factory_set_xy2(Object_t *obj, guint state, gint x, gint y)
  383. {
  384.    Circle_t *circle = ObjectToCircle(obj);
  385.  
  386.    x -= circle->x;
  387.    y -= circle->y;
  388.    circle->r = (gint) sqrt(x * x + y * y);
  389.  
  390.    main_set_dimension(circle->r, circle->r);
  391. }
  392.  
  393. static ObjectFactory_t circle_factory2 = {
  394.    NULL,            /* Object pointer */
  395.    NULL,            /* Finish func */
  396.    NULL,            /* Cancel func */
  397.    circle_factory_create_object2,
  398.    circle_factory_set_xy2
  399. };
  400.  
  401. ObjectFactory_t*
  402. get_circle_factory(guint state)
  403. {
  404.    return (state & GDK_SHIFT_MASK) ? &circle_factory1 : &circle_factory2;
  405. }
  406.